/**
 * <p>Title: EllipseListGUI</p>
 * <p>Description: CS 235 Assignment #3</p>
 * @author Erin McNeil
 * @email erin.mcneil@my.uwrf.edu
 * @date 12/2/2011
 * @team Erin, Dara, Alan
 */

package a3;

import java.awt.event.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * EllipseList Graphical User Interface
 */
public class EllipseListGUI extends JFrame implements ActionListener {

	/**
	 * Data members for the GUI interface
	 */
	private static final long serialVersionUID = 1L;
	private final int FRAME_X = 100, FRAME_Y = 100, FRAME_WIDTH = 600,
			FRAME_HEIGHT = 600;
	private final int SCROLL_X = 30, SCROLL_Y = 30, SCROLL_WIDTH = 600,
			SCROLL_HEIGHT = 400;
	private final int SORT_X = 30, SORT_Y = 235, SORT_WIDTH = 100,
			SORT_HEIGHT = 30;
	private String MAJOR_STRING = "Major Axis";
	private String MINOR_STRING = "Minor Axis";
	private String PERIMETER_STRING = "Perimeter";
	private String AREA_STRING = "Area";
	private JList listview;
	private JScrollPane scroll;
	private DefaultListModel ellipseModel;
	private Vector<CreateEllipse> ellipseList;
	private JMenuItem menuNew;
	private JMenuItem menuOpen;
	private JMenuItem menuSave;
	private final JFileChooser chooser = new JFileChooser();

	private JButton major;
	private JButton minor;
	private JButton perimeter;
	private JButton area;

	// Constructor for the EllipseListGUI:

	/**
	 * EllipseListGUI constructor. Creating the GUI.
	 * 
	 * @require
	 * @ensure ellipses.length == 22
	 * 
	 */
	public EllipseListGUI(String title) {
		super(title);
		setBounds(FRAME_X, FRAME_Y, FRAME_WIDTH, FRAME_HEIGHT);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		setLayout(null);

		/*
		 * Ellipse Data that will be used as the "Ellipse Model"
		 */
		CreateEllipse[] ellipses = new CreateEllipse[22];

		for (int i = 0; i < ellipses.length; i++) {
			ellipses[i] = new CreateEllipse(1000 * Math.random(), 1000 * Math
					.random());
		}

		/*
		 * adding the elements of array ellipses into the ellipseModel
		 */
		ellipseModel = new DefaultListModel();
		for (CreateEllipse s : ellipses)
			ellipseModel.addElement(s);

		/*
		 * Now that the data is available, set up GUI elements to display it.
		 */
		listview = new JList(ellipseModel);
		listview.setVisible(true);
		scroll = new JScrollPane(listview);
		scroll.setBounds(SCROLL_X, SCROLL_Y, SCROLL_WIDTH, SCROLL_HEIGHT);
		add(scroll);

		// Creating the 4 buttons:

		/*
		 * creating Major Axis button
		 */
		major = new JButton(MAJOR_STRING);
		major.addActionListener(this);
		major.setBounds(SORT_X, SORT_Y + 200, SORT_WIDTH, SORT_HEIGHT);
		add(major);

		/*
		 * creating Minor Axis button
		 */
		minor = new JButton(MINOR_STRING);
		minor.addActionListener(this);
		minor.setBounds(SORT_X + 100, SORT_Y + 200, SORT_WIDTH, SORT_HEIGHT);
		add(minor);

		/*
		 * creating Perimeter button
		 */
		perimeter = new JButton(PERIMETER_STRING);
		perimeter.addActionListener(this);
		perimeter
				.setBounds(SORT_X + 200, SORT_Y + 200, SORT_WIDTH, SORT_HEIGHT);
		add(perimeter);

		/*
		 * creating Area button
		 */
		area = new JButton(AREA_STRING);
		area.addActionListener(this);
		area.setBounds(SORT_X + 300, SORT_Y + 200, SORT_WIDTH, SORT_HEIGHT);
		add(area);

		setVisible(true);

		// Creating the File Menu with the 3 File Items: New, Open, and Save.

		/*
		 * creating the menuBar
		 */
		JMenuBar menuBar = new JMenuBar();

		/*
		 * creating the filemenu
		 */
		JMenu filemenu = new JMenu("File");
		menuBar.add(filemenu);

		/*
		 * creating the "New" MenuItem
		 */
		menuNew = new JMenuItem("New");
		menuNew.addActionListener(this);
		filemenu.add(menuNew);

		/*
		 * creating the "Open" MenuItem
		 */
		menuOpen = new JMenuItem("Open");
		menuOpen.addActionListener(this);
		filemenu.add(menuOpen);

		/*
		 * creating the "Save" MenuItem
		 */
		menuSave = new JMenuItem("Save");
		menuSave.addActionListener(this);
		filemenu.add(menuSave);

		setJMenuBar(menuBar);

	}

	// actionPerformed Methods:

	/**
	 * actionPerformed - Method to sort the list of ellipses by the Major Axis,
	 * the Minor Axis, the Perimeter, or the Area. Also used to clear the list
	 * by using "New", save the current list of ellipses by using "Save", or
	 * open a list of ellipses by using "Open".
	 * 
	 * @require
	 * @ensure ellipseModel.getSize() == 22
	 */
	public void actionPerformed(ActionEvent ae) {
		Object source = ae.getSource();

		/*
		 * If the user clicks the "Major Axis" button.
		 */
		if (source.equals(major)) {
			if (major.getText().equals(MAJOR_STRING)) {

				/*
				 * copying the ellipseModel into a Vector<CreateEllipse> called
				 * ellipseList
				 */

				ellipseList = new Vector<CreateEllipse>();

				for (int i = 0; i < 22; i++)
					ellipseList.addElement((CreateEllipse) ellipseModel
							.elementAt(i));
				/*
				 * deleting everything from the ellipseModel
				 */
				ellipseModel.clear();

				/*
				 * Sorting the Vector<ellipseModel> by the Major Axis by
				 * calling the CompareMajor Comparator
				 */
				Collections.sort(ellipseList, new CompareMajor());

				/*
				 * putting the Vector or ArrayList into the (now empty)
				 * ellipseModel
				 */
				for (int i = 0; i < 22; i++)
					ellipseModel.addElement(ellipseList.elementAt(i));

			}
		}

		/*
		 * If the user clicks the "Minor Axis" button.
		 */
		else if (source.equals(minor)) {
			if (minor.getText().equals(MINOR_STRING)) {

				/*
				 * copying the ellipseModel into a Vector<CreateEllipse> called
				 * ellipseList
				 */

				ellipseList = new Vector<CreateEllipse>();

				for (int i = 0; i < 22; i++)
					ellipseList.addElement(((CreateEllipse) ellipseModel
							.elementAt(i)));

				/*
				 * deleting everything from the ellipseModel
				 */
				ellipseModel.clear();

				/*
				 * Sorting the Vector<EllipseList> based on the minor axis by
				 * calling the CompareMinor Comparator
				 */
				Collections.sort(ellipseList, new CompareMinor());

				/*
				 * putting the Vector or ArrayList into the (now empty)
				 * ellipseModel
				 */
				for (int i = 0; i < 22; i++)
					ellipseModel.addElement(ellipseList.elementAt(i));

			}

		}

		/*
		 * If the user clicks the "Perimeter" button.
		 */
		if (source.equals(perimeter)) {
			if (perimeter.getText().equals(PERIMETER_STRING)) {

				/*
				 * copying the ellipseModel into a Vector<CreateEllipse> called
				 * ellipseList
				 */

				ellipseList = new Vector<CreateEllipse>();

				for (int i = 0; i < 22; i++)
					ellipseList.addElement(((CreateEllipse) ellipseModel
							.elementAt(i)));

				/*
				 * deleting everything from the ellipseModel
				 */
				ellipseModel.clear();

				/*
				 * Sorting the Vector<CreateEllipses> based on the perimeter by
				 * calling the ComparePerimeter Comparator
				 */
				Collections.sort(ellipseList, new ComparePerimeter());

				/*
				 * putting the Vector or ArrayList into the (now empty)
				 * ellipseModel
				 */
				for (int i = 0; i < 22; i++)
					ellipseModel.addElement(ellipseList.elementAt(i));

			}
		}

		/*
		 * If the user clicks the "Area" button.
		 */
		if (source.equals(area)) {
			if (area.getText().equals(AREA_STRING)) {

				/*
				 * copying the ellipseModel into a Vector<CreateEllipse> called
				 * ellipseList
				 */

				ellipseList = new Vector<CreateEllipse>();

				for (int i = 0; i < 22; i++)
					ellipseList.addElement(((CreateEllipse) ellipseModel
							.elementAt(i)));

				/*
				 * deleting everything from the ellipseModel
				 */
				ellipseModel.clear();

				/*
				 * Sorting the Vector<CreateEllipse> by the area by calling the
				 * CompareArea Comparator
				 */
				Collections.sort(ellipseList, new CompareArea());

				/*
				 * putting the Vector or ArrayList into the (now empty)
				 * ellipseModel
				 */
				for (int i = 0; i < 22; i++)
					ellipseModel.addElement(ellipseList.elementAt(i));

			}
		}

		/*
		 * If the user clicks "New" from the File Menu, clearing the
		 * ellipseModel, therefore clearing the list.
		 */
		if (ae.getSource() == menuNew) {

			ellipseModel.clear();

		}
		/*
		 * If the user clicks "Open" from the File Menu, opening the specific
		 * file as an array and then storing that array into the ellipseModel.
		 */
		if (ae.getSource() == menuOpen) {
			int result = chooser.showOpenDialog(this);
			if (result == JFileChooser.APPROVE_OPTION) {

				try {
					ObjectInputStream ois = new ObjectInputStream(
							new FileInputStream(chooser.getSelectedFile()));
					CreateEllipse[] ellipses3 = new CreateEllipse[22];
					ellipses3 = (CreateEllipse[]) ois.readObject();
					
					ellipseList = new Vector<CreateEllipse>();
					boolean flag = ellipseList.isEmpty();
					if(flag == false){
					ellipseList.clear();
					}
					
					for (CreateEllipse e : ellipses3)
						ellipseList.add(e);

				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}

			}
			ellipseModel.clear();
			for (CreateEllipse s : ellipseList)
				ellipseModel.addElement(s);
		}

		/*
		 * If the user clicks "Save" from the File Menu, saving the ellipseModel
		 * as an array to a file.
		 */
		if (ae.getSource() == menuSave) {
			int result = chooser.showSaveDialog(this);
			if (result == JFileChooser.APPROVE_OPTION) {
				try {

					ObjectOutputStream os = new ObjectOutputStream(
							new FileOutputStream(chooser.getSelectedFile()));

					CreateEllipse[] ellipses2 = new CreateEllipse[ellipseModel
							.getSize()];
					for (int i = 0; i < ellipseModel.getSize(); i++) {
						ellipses2[i] = ((CreateEllipse) (ellipseModel
								.elementAt(i)));

					}

					os.writeObject(ellipses2);
					os.close();
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	// Comparators:

	/**
	 * Comparator CompareMajor
	 */
	class CompareMajor implements Comparator<CreateEllipse> {
		
		/**
		 * Comparator CompareMajor - used to sort the list of ellipses by the Major
		 * Axis.
		 * 
		 * @require
		 * @ensure returns +1 || returns -1 || returns 0
		 */
		public int compare(CreateEllipse arg0, CreateEllipse arg1) {

			if (arg0.major_axis > arg1.major_axis)

				return +1;

			if (arg0.major_axis < arg1.major_axis)

				return -1;

			return 0;

		}

	}

	/**
	 * Comparator CompareMinor
	 */
	class CompareMinor implements Comparator<CreateEllipse> {

		/**
		 * Comparator CompareMinor - used to sort the list of ellipses by the Minor
		 * Axis.
		 * 
		 * @require
		 * @ensure returns +1 || returns -1 || returns 0
		 */
		public int compare(CreateEllipse arg0, CreateEllipse arg1) {

			if (arg0.minor_axis > arg1.minor_axis)

				return +1;

			if (arg0.minor_axis < arg1.minor_axis)

				return -1;

			return 0;

		}

	}

	/**
	 * Comparator ComparePerimeter
	 */
	class ComparePerimeter implements Comparator<CreateEllipse> {

		/**
		 * Comparator ComparePerimeter - used to sort the list of ellipses by the
		 * Perimeter.
		 * 
		 * @require
		 * @ensure returns +1 || returns -1 || returns 0
		 */
		public int compare(CreateEllipse arg0, CreateEllipse arg1) {

			if (arg0.Eperimeter > arg1.Eperimeter)

				return +1;

			if (arg0.Eperimeter < arg1.Eperimeter)

				return -1;

			return 0;

		}

	}

	/**
	 * Comparator CompareArea
	 */
	class CompareArea implements Comparator<CreateEllipse> {

		/**
		 * Comparator CompareArea - used to sort the list of ellipses by the Area.
		 * 
		 * @require
		 * @ensure returns +1 || returns -1 || returns 0
		 */
		public int compare(CreateEllipse arg0, CreateEllipse arg1) {

			if (arg0.Earea > arg1.Earea)

				return +1;

			if (arg0.Earea < arg1.Earea)

				return -1;

			return 0;

		}

	}

	// Main Method:

	/**
	 * Main Method
	 * 
	 * @require
	 * @ensure
	 */
	public static void main(String[] args) {
		new EllipseListGUI("My Ellipse System");
	}
}
